#pragma once
#include "Connection.hpp"


class io_connection : public connection
{
protected:
    
    //io_connection类里[所有的]异常都会被归总到该函数中进行处理 -- 关闭本连接
    virtual void exception_handler() override;//因为内部使用的未完全定义的类型: _server回指指针, 所以要头源分离



public:
    io_connection(int sockfd, uint32_t events, const Inet_Addr& client)
        :connection(sockfd, events)//初始化基类成员
        ,_client(client)
    {
        set_no_block(_sockfd_ptr->get_socket_fd());//设置io_sockfd为非阻塞
    }



    //1. 读事件就绪了, 不能保证一次能把本轮数据读完 -- 在ET模式下: [必须]一次把所有数据全部读上来 -- while非阻塞读
    //2. 即便是把本轮数据读完, 因为tcp面向字节流(报文不全, 粘包...), 需要完整性检查和序列化反序列化 --- 引入协议层
    virtual void receive() override
    {
        std::cout << "进入io_connection::receive" << std::endl;
        while(true)
        {
            int recv_count = _sockfd_ptr->receive(_in_buffer);
            if(recv_count > 0) //读到数据了
                continue;//继续读, 知道把底层缓冲区里的这波数据读完

            else if(recv_count == 0)//对端关闭了
            {
                exception_handler();
                return;//处理完直接return
            }
            else //recv_count < 0
            {
                if(recv_count == RECEIVE_DONE)//读完了, 内核buffer没有数据了
                    break;
                
                else if(recv_count == RECEIVE_CONTINUE)
                    continue;
                
                else
                {
                    LOG(wzx::log_level::ERROR) << "io_connection::receive unknown fail !!!";
                    exception_handler();
                    return;//处理完直接return
                }
            }
        }  
        //出循环代表receive没出错, 且底层缓冲区里的这波数据已经读完了 --> 处理数据
        if(!_in_buffer.empty())
            _out_buffer += _io_handle_func(_in_buffer);//调用回调函数, 将数据(输入/输出缓冲区)从表示层递出, 交给上层(会话层)处理

        //有数据就直接发
        if (!_out_buffer.empty())
            send(); 
    }



    virtual void send() override; //因为内部使用的未完全定义的类型: _server回指指针, 所以要头源分离




protected:
    //每一条连接都有自己的读写缓冲区, 多连接时就不怕线程安全问题了
    std::string _in_buffer;//vector<char>
    std::string _out_buffer;

    Inet_Addr _client;

    
};